大家好,我是 Eric。
昨天介紹了 PHP 變數與函式的基本定義方式,接下來我們要介紹 WordPress 中扮演要角的函式們:勾點 (Hook)。所謂的勾點,就是在整個網頁在計算過程中,在特定階段執行特定行為的函式。
勾點分為兩種:篩選器 (filter) 與動作 (action)。
動作勾點的基本語法如下:
do_action( '動作勾點名稱' );
add_action( '動作勾點名稱', '函式名稱', '優先度 (整數,選填)', '接受參數 (整數,選填)' );
根據 WordPress Codex 的定義,動作指的是
在 WordPress 事件發生時,同時觸發特定函式 (functions)。
或者說:
「WordPress 正在 OOO,這時候我也 XXX。」
簡單來說,我們可以透過 add_action
的方式,將函式的程式碼片段插入 do_action
的位置。舉例來說,我們在自訂的 Twenty Twenty 子佈景主題中加入 header.php 檔案,用以取代上層佈景主題,接著在第 27 行加入一段 do_action
:
<body <?php body_class(); ?>>
<?php
do_action( 'before_wp_body_open' );
wp_body_open();
?>
接著,我們在子佈景主題的 functions.php 中加入下列程式碼片段:
add_action( 'before_wp_body_open', 'do_me_before' );
function do_me_before(){
echo '<p>我會比 wp_body_open 還要早出現。</p>';
}
add_action( 'wp_body_open', 'the_open_part' );
function the_open_part(){
echo '<p>這是 wp_body_open 出現的時機。</p>';
}
在上述的例子中,會看到 do_me_before
的段落元素出現在 the_open_part
之前。而在這兩個段落出現後,才會看到網頁剩下的內容 (頁首、導覽列等)。
如果有多個函式指向同一個勾點,那麼就會有優先順序的問題,此時就要透過 add_action( '勾點名稱', '函式名稱', 10 );
的方式指定順序。預設值是 10,數字越大越後面才執行,因此如果有外掛發生衝突的時候,不妨檢查看看是不是有多個外掛同時使用到同一個動作勾點。
還記得我們在前面曾經看過 add_action( 'wp_enqueue_scripts', 'function_name' );
嗎?這個勾點便是在告訴 WordPress 在載入 JavaScript 程式碼與 CSS 樣式表的時候,將 wp_enqueue_script
與 wp_enqueue_style
中的樣式一併載入。
關於 WordPress 核心程式的動作順序,可以參考這篇文章。
篩選器的基本語法是:
apply_filters( '篩選器勾點名稱' );
add_filter( '篩選器勾點名稱', '函式名稱', '優先度 (整數,選填)', '接受參數 (整數,選填)' );
根據 WordPress Codex 的定義,篩選器指的是
在 WordPress 將資料於資料庫與瀏覽器間傳遞的過程中,篩選特定資料並回傳已經過轉換的值。
或者說:
現在 WordPress 正要輸出/入 OOO,但我想先 XXX。
和 do_action
類似,我們可以透過 apply_filters
的方法,在自己所希望的位置添加篩選器。
我們可以參考 template-parts/content.php 程式碼中的第 32 行:
/* Line 32 */
if ( is_search() || ! is_singular() && 'summary' === get_theme_mod( 'blog_content', 'full' ) ) {
the_excerpt();
} else {
the_content( __( 'Continue reading', 'twentytwenty' ) );
}
我們接著查詢 the_content
這個函式,看到這個函式的主要內容是 apply_filters( 'the_content' );
的內容:
function the_content( $more_link_text = null, $strip_teaser = false ) {
$content = get_the_content( $more_link_text, $strip_teaser );
/**
* Filters the post content.
*
* @since 0.71
*
* @param string $content Content of the current post.
*/
$content = apply_filters( 'the_content', $content );
$content = str_replace( ']]>', ']]>', $content );
echo $content;
}
因此我們如果用 add_filter
的篩選器勾點,先將文章內容 $content
進行處理,那麼這段被處理過的內容,會再作後再透過 str_replace
這個函式,將 ]]>
取代為 ]]>
。
如果你安裝了 WordPress 官方開發的 AMP 外掛,當你啟用閱讀器模式時,並不會安裝網路字型。因此,我們可以透過 AMP 提供的勾點,加入自訂的網路字型:
add_filter( 'amp_post_template_data', function( $data ){
$data['font_urls'] = array(
'custom' => 'https://fonts.googleapis.com/css2?family=Noto+Sans+TC&family=Ubuntu&display=swap',
);
return $data;
});
add_action( 'amp_post_template_css', function(){ ?>
body
{
font-family: "Ubuntu", "Noto Sans TC", sans-serif;
}
<?php });
有關 WordPress 的 AMP 外掛說明,可以參考其官方網站,在這個頁面中可以查詢到更多不同的延伸應用。
在大多數的網站安全性文章中,都會提到「靜態資源的版本資訊是安全漏洞」。這是因為有些漏洞公諸於世後,一旦有心人士注意到你的網站使用的是舊版檔案,便可能使用該漏洞攻擊你的網站。因此移除靜態資源的版本資訊,算是網站安全的基本設定之一。
function remove_version_query( $src ) {
if ( strpos( $src, 'ver=' ) ) {
$src = remove_query_arg( 'ver', $src );
}
return $src;
}
add_filter( 'style_loader_src', 'remove_version_query', 999 );
add_filter( 'script_loader_src', 'remove_version_query', 999 );
這個程式碼片段會在樣式表的 <link>
元素與 <script>
元素輸出至頁面前,查詢靜態檔案來源網址中是否有 ver
這個參數,如果有,便將該參數移除。
名稱 | 類型 | 說明
------+------+------
wp_enqueue_scripts | action | WordPress 開始引入 CSS、JS 檔案時的動作。
wp_head | action | 所有會在 wp_head() 執行時的動作,包含載入頁面中繼資料 (meta)、引入 CSS、JS 檔案等。
the_post | action | 在 WordPress 完成文章查詢請求後的動作。
wp_footer | action | 所有會在 wp_footer() 執行時的動作,譬如載入客製化的 JavaScript 等。
body_class | filter | 在導出 body 元素的 CSS 類型時進行篩選、改寫。
get_the_excerpt | filter | 在取得文章內容摘要時,進行篩選、改寫。可用於自訂文章內容摘要長度的時候。
manage_posts_columns | filter | 在各文章類型 (post type) 的管理頁面中,顯示特定欄位時使用。
the_content | filter | 篩選文章內容,可以搭配 preg_replace 等方式,取代文章中的特定字元。
在進入 PHP 篇章後,我們會開始更廣泛的使用勾點的方式來進行客製化。
不只是 WordPress 的核心程式,許多外掛也會透過勾點的方式來提高客製化的彈性。以 Contact Form 7 為例,它也提供了許多勾點,在產生表單的 HTML 代碼前,可以先將表單處理過。
在透過 WordPress 的勾點機制進行客製化前,你可以像前面探討 apply_filters
的方式,透過追蹤函式的定義,找到最根本的勾點,並透過 add_action
與 add_filter
來客製化不同的功能。
明天我們會介紹 WordPress 客製化的另一個重要元素:自訂內容類型 (Custom Post Type)。
勾點 (Hook) 初探
WordPress的Hook機制與原理
【第 04 天】聊聊 WordPress 的 Action Hooks
【第 05 天】聊聊 WordPress 的 Filter Hooks